﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Aspose.Words;

namespace CDDocumentExtractor
{
    public interface ITracer
    {
        void WriteLine(string msg);
    }

    public class Common
    {

        public static void CreateDocumentPDFs(string folderPath,ITracer tempTracer = null)
        {
            ITracer tracer = tempTracer;

            if (!Directory.Exists(folderPath))
                return;

            var SectionPDFs = Directory.GetFiles(folderPath, "*.pdf", SearchOption.AllDirectories);

            Console.WriteLine("Total Files to Process : " + SectionPDFs.Length.ToString());
            if (tracer != null)
                tracer.WriteLine("Total Files to Process : " + SectionPDFs.Length.ToString());

            foreach (var file in SectionPDFs)
            {
                try
                {
                    Console.WriteLine(file);
                    if (!Path.GetFileNameWithoutExtension(file).StartsWith("Doc"))
                    {
                        var Documentfolder = Path.GetDirectoryName(file);
                        var dinfo = new DirectoryInfo(Documentfolder);
                        string folderName = dinfo.Name;
                        Console.WriteLine("Working on Document : " + folderName);
                        if (tracer != null)
                            tracer.WriteLine("Working on Document : " + folderName);

                        string DocumentFileName = string.Format("Doc_{0}.pdf", folderName);
                        string newFilePath = Path.Combine(Documentfolder, DocumentFileName);
                        TryDelete(newFilePath);
                        File.Copy(file, newFilePath);
                        Console.WriteLine("Created : " + newFilePath);
                        if (tracer != null)
                            tracer.WriteLine("Created : " + newFilePath);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception occured in : " + file);
                    Console.WriteLine(ex.Message);
                    Console.WriteLine("***************");
                    Console.WriteLine(ex.StackTrace);
                    if (tracer!=null)
                    {
                        tracer.WriteLine("Exception occured in : " + file);
                        tracer.WriteLine(ex.Message);
                        tracer.WriteLine("***************");
                        tracer.WriteLine(ex.StackTrace);
                    }
                }
            }
        }


        /// <summary>
        /// This method will generate and update InfoOne Citation Nos into InfoOne Database.
        /// </summary>
        public static void GenerateAndUpdateInfoOneCitationNos()
        {
            using (var db = new I1DBModelDataContext())
            {
                db.CommandTimeout = 0;

                using (var scope = new System.Transactions.TransactionScope())
                {
                    db.ExecuteCommand("exec dbo.usp_temp_GenerateInfoOneCitations");
                        scope.Complete();
                }
                //StringBuilder sb = new StringBuilder();
                //sb.AppendLine("WITH InfoOneJudgements (DocumentID, DocumentIssueDate, CourtNameId)");
                //sb.AppendLine("AS");
                //sb.AppendLine("(");
                //sb.AppendLine("	SELECT TOP 100 PERCENT DocumentID, DocumentIssueDate, CourtNameId");
                //sb.AppendLine("		FROM DocumentMeta");
                //sb.AppendLine("	Order By DocumentIssueDate");
                //sb.AppendLine(")");

                //sb.AppendLine("UPDATE dm");
                //sb.AppendLine("	SET InfoOneCitation = [dbo].[GetInfoOneCitation](ij.CourtNameId, ij.DocumentIssueDate)");
                //sb.AppendLine("FROM DocumentMeta AS dm");
                //sb.AppendLine("JOIN InfoOneJudgements AS ij ");
                //sb.AppendLine("	ON dm.DocumentID = ij.DocumentID");
                //sb.AppendLine("	WHERE dm.ManupatraCitation like 'MANU%' AND dm.InfoOneCitation IS NULL");
                ////sb.Append("GO");

                //db.ExecuteCommand(sb.ToString());
            }
        }

        public static List<string> GetTags(string tag, string DataToCheck)
        {
            //string exp = "<" + tag + "\\b[^>]*>(.*?)</" + tag + ">";
            string exp = "<" + tag + "[^>]*>(.*?)</" + tag + ">"; //<citingref[^>]*>(.*?)</citingref>
            List<string> list = new List<string>();
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);

            var matches = rx.Matches(DataToCheck);
            foreach (System.Text.RegularExpressions.Match match in matches)
            {
                list.Add(match.Value);
            }

            return list;
        }

        public static List<string> GetTagValues(string tag, string DataToCheck)
        {
            string exp = "<" + tag + "[^>]*>(.*?)</" + tag + ">";
            List<string> list = new List<string>();
            System.Text.RegularExpressions.Regex rx = new System.Text.RegularExpressions.Regex(exp, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);

            var matches = rx.Matches(DataToCheck);
            foreach (System.Text.RegularExpressions.Match match in matches)
            {
                string val = System.Text.RegularExpressions.Regex.Replace(match.Value, "<.*?>", string.Empty);
                if (val.Trim().Length > 0)
                {
                    string parsedValue = val.Trim();
                    int i = 0;
                    while (i < 10 && (parsedValue.EndsWith(",") || parsedValue.EndsWith("and")))
                    {

                        if (parsedValue.EndsWith(","))
                        {
                            parsedValue = parsedValue.Length > 1 ? parsedValue.Substring(0, parsedValue.Length - 1) : parsedValue;
                        }

                        if (parsedValue.EndsWith("and"))
                        {
                            parsedValue = parsedValue.Length > 3 ? parsedValue.Substring(0, parsedValue.Length - 3) : parsedValue;
                        }
                        i++;
                    }

                    list.Add(parsedValue);
                }
            }

            return list;
        }

        /// <summary>
        /// This method will process document to update all the links
        /// All links will be replaced by InfoOne Links
        /// </summary>
        public static void ParseLinksInDocument(ITracer tracertemp=null)
        {
            ITracer tracer = tracertemp;
            string RegEx_ManuID = "MANU\\x2F\\w*\\x2F\\d*\\x2F\\d{4}";

            using (var db = new I1DBModelDataContext())
            {
                //Get List of All Documents
                var docs = from ds in db.DocumentSections
                           join dmeta in db.DocumentMetas on ds.DocumentID equals dmeta.DocumentID
                           where dmeta.DocumentType == 1 && dmeta.ManupatraCitation!=null
                           && dmeta.ManupatraCitation != ""
                           //dmeta.EquivalentCitation=="PRC"
                           //    //  ds.DocumentMaster.IsPublished == false &&
                           //dmeta.DocumentType==1                //.EquivalentCitation=="PRC"
                           //&& ds.DocumentMaster.IsPublished == false
                           //    //ds.DocumentMaster.Notes != "Bulk Import"
                           ////&& dmeta.DocumentType==1
                           select new
                           {
                               DocumentID = (System.Int32?)ds.DocumentMaster.DocumentID,
                               DocumentPath = ds.DocumentMaster.Path,
                               ManupatraCitation = dmeta.ManupatraCitation,
                               SectionPath = ds.Path,
                               PublishedPath = ds.PublishedPath,
                               InfoOneCitation = dmeta.InfoOneCitation,
                               IsPublished = ds.DocumentMaster.IsPublished.HasValue && ds.DocumentMaster.IsPublished.Value
                           };

                //All Judgements
                var documents = docs.ToList();

                //Get list of unpublished documents
                var searchedDocs = documents.FindAll(dfe => !dfe.IsPublished);

                Console.WriteLine("Working on Total : " + searchedDocs.Count.ToString());
                if (tracer!=null)
                    tracer.WriteLine("Working on Total : " + searchedDocs.Count.ToString());

                //Process all documents
                foreach (var document in searchedDocs)
                {
                    //Variable used to check if all the links are processed or not.
                    var ProcessingComplete = true;
                    try
                    {
                        string filePath = Path.Combine(WebUtility.SourceFolder, "PROCESSED_" + document.ManupatraCitation.Replace('/', '_') + ".txt");
                        if (File.Exists(filePath))
                        {
                            Console.WriteLine("Working on : " + document.ManupatraCitation);
                            if (tracer != null)
                                tracer.WriteLine("Working on : " + document.ManupatraCitation);

                            string DocumentData = File.ReadAllText(filePath);
                            var links = Common.GetTags("a", DocumentData);

                            var listRelations = new List<DocumentRelation>();

                            //If its a MANU link
                            if (links.Count > 0 && links.Count(lnk => lnk.Contains("MANU")) > 0)
                            {
                                //Code below will remove any extra text from the link text and provide only manu ids
                                for (int i = 0; i < links.Count; i++)
                                {
                                    var link = new ManuLinkEntity();
                                    link.LinkTag = links[i];

                                    //Link Text
                                    link.LinkText = System.Text.RegularExpressions.Regex.Replace(link.LinkTag, "<.*?>", string.Empty);

                                    //Manu ID
                                    System.Text.RegularExpressions.Regex rxManuID = new System.Text.RegularExpressions.Regex(RegEx_ManuID, System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
                                    link.ManuCitation = rxManuID.Match(link.LinkTag).Value.Trim();

                                    var relatedDocument = documents.Find(df => df.ManupatraCitation == link.ManuCitation); //dmetaQuery.FirstOrDefault();
                                    if (relatedDocument != null)
                                    {
                                        //Create Relation for this document
                                        listRelations.Add(new DocumentRelation()
                                        {
                                            DocumentID = document.DocumentID,
                                            Createdby = 1,
                                            CreatedDate = DateTime.Now,
                                            RelatedDocumentID = relatedDocument.DocumentID,
                                            IsPublished = true
                                        });

                                        //Get Linked Document Info
                                        link.InfoOneID = relatedDocument.DocumentID.Value;
                                        link.InfoOneCitation = relatedDocument.InfoOneCitation;

                                        //Replace Manu IDs from Link Text with InfoOne Citation
                                        //link.LinkText = rxManuID.Replace(link.LinkText, link.InfoOneCitation);
                                        link.LinkText = rxManuID.Replace(link.LinkText, "<a href='http://www.infooneplus.com/documentviewer.aspx?id=" + link.InfoOneID.ToString() + "'>" + link.InfoOneCitation + "</a>");

                                        DocumentData = DocumentData.Replace(link.LinkTag, link.LinkText);
                                    }
                                    else
                                    {
                                        //One of the link cannot be found hence don't publish
                                        ProcessingComplete = false;
                                    }
                                }
                            }

                            string strUpdateQuery = "UPDATE DocumentMaster SET IsPublished=1 Where DocumentID=" + document.DocumentID.ToString();
                            if (ProcessingComplete && db.ExecuteCommand(strUpdateQuery) > 0)
                            {
                                //Save All Relations into Database
                                if (listRelations.Count > 0)
                                {
                                    foreach (var relations in listRelations)
                                    {
                                        db.DocumentRelations.InsertOnSubmit(relations);
                                    }

                                    db.SubmitChanges();
                                }

                                //Write Updated Text into File
                                File.Move(filePath, Path.Combine(WebUtility.ArchieveFolder, "PROCESSED_" + document.ManupatraCitation.Replace('/', '_') + ".txt"));
                                //File.WriteAllText(filePath, DocumentData);

                                string htmlPath = Path.Combine(WebUtility.DocumentsFolder.Replace("-main", ""), document.DocumentPath);
                                //Generating Files
                                if (File.Exists(htmlPath))
                                    File.Delete(htmlPath);

                                File.WriteAllText(htmlPath, DocumentData);

                                if (DocumentData.Length > 0)
                                {
                                    Aspose.Words.Document doc = new Aspose.Words.Document(htmlPath);
                                    doc.ViewOptions.ViewType = Aspose.Words.Settings.ViewType.PageLayout;

                                    foreach (Aspose.Words.Section item in doc.Sections)
                                    {
                                        foreach (Aspose.Words.Paragraph paras in item.Body.Paragraphs)
                                        {
                                            paras.ParagraphFormat.Alignment = Aspose.Words.ParagraphAlignment.Justify;
                                            paras.ParagraphFormat.Style.Font.Name = "Arial";
                                        }
                                    }

                                    string docxPath = Path.Combine(WebUtility.DocumentsFolder, document.DocumentPath.Replace(".htm", ".docx"));
                                    string pdfPath = Path.Combine(WebUtility.DocumentsFolder, document.PublishedPath.Replace(".htm", ".pdf"));
                                    string secpdfPath = docxPath;// Path.Combine(WebUtility.DocumentsFolder, document.SectionPath);

                                    Directory.CreateDirectory(Path.GetDirectoryName(docxPath));
                                    Directory.CreateDirectory(Path.GetDirectoryName(pdfPath));
                                    Directory.CreateDirectory(Path.GetDirectoryName(secpdfPath));

                                    //Save to Docx
                                    TryDelete(docxPath);
                                    doc.Save(docxPath, Aspose.Words.SaveFormat.Docx);

                                    //Save the PDF
                                    TryDelete(pdfPath);
                                    doc.Save(pdfPath, Aspose.Words.SaveFormat.Pdf);

                                    //this will be created after the whole generation process
                                    //Save the Section PDF
                                    //TryDelete(secpdfPath);
                                    //doc.Save(secpdfPath, Aspose.Words.SaveFormat.Pdf);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (tracer != null)
                        {
                            tracer.WriteLine(document.ManupatraCitation + "***" + document.DocumentID);
                            tracer.WriteLine("*********************************************");
                            tracer.WriteLine(ex.Message);
                            tracer.WriteLine("*********************************************");
                            tracer.WriteLine(ex.StackTrace);
                        }
                    }
                }
            }
        }

       
        public static void TryDelete(string path)
        {
            try
            {
                File.Delete(path);
            }
            catch
            {
            }
        }

    }
}
